home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / lm / upgradeLock.c < prev   
Encoding:
C/C++ Source or Header  |  1996-05-05  |  6.8 KB  |  241 lines

  1. /*
  2.  *   $RCSfile: upgradeLock.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:51 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38. #include "sysdefs.h"
  39. #include "ess.h"
  40. #include "checking.h"
  41. #include "trace.h"
  42. #include "error.h"
  43. #include "list.h"
  44. #include "pool.h"
  45. #include "tid.h"
  46. #include "io.h"
  47. #include "lock.h"
  48. #include "object.h"
  49. #include "msgdefs.h"
  50. #include "thread.h"
  51. #include "semaphore.h"
  52. #include "link.h"
  53. #include "lsn.h"
  54. #include "latch.h"
  55. #include "bf.h"
  56. #include "volume.h"
  57. #include "trans.h"
  58. #include "threadstate.h"
  59. #include "lm_intfuncs.h"
  60. #include "lm_extfuncs.h"
  61. #include "thread_funcs.h"
  62. #include "lock_globals.h"
  63. #include "thread_globals.h"
  64.  
  65.  
  66.  int
  67. upgradeLock (
  68.  
  69.     register TRANSREC    *transRec,
  70.     register LOCKHEADER    *lockHeader,
  71.     register LOCKENTRY    *lockEntry,
  72.     LOCKMODE            requestMode,
  73.     FLAGS                flags 
  74. )
  75. {
  76.  
  77.     register LOCKMODE    newMode;
  78.  
  79.  
  80.     TRPRINT(TR_LOCK, TR_LEVEL_1, ("request mode:%s", GETMODE(requestMode)));
  81.  
  82.     /*
  83.      *    get the mode to upgrade to
  84.      */
  85.     newMode = LM_Convert[lockEntry->lockMode][requestMode];
  86.     TRPRINT(TR_LOCK, TR_LEVEL_2, ("newMode:%s", GETMODE(newMode)));
  87.  
  88.     /*
  89.      *    remove the lock held by requestor from the list
  90.      *    and decrement the mode of the lock
  91.      */
  92.     listRemove( &(lockEntry->headerList.list) );
  93.     lockHeader->modeCount[lockEntry->lockMode]--;
  94.  
  95.     /*
  96.      *    check to see if the request is compatible with
  97.      *    the already granted locks
  98.      */
  99.     if (lockCompatible(lockHeader, newMode))    {
  100.  
  101.         TRPRINT(TR_LOCK, TR_LEVEL_2, ("lock is compatible"));
  102.  
  103.         /*
  104.          *    alter the lock status
  105.          */
  106.         lockHeader->modeCount[newMode]++;
  107.  
  108.         /*
  109.          *    check for a new supremum
  110.          */
  111.         if (!LM_Compat_Upgrade[newMode][lockHeader->supremum])    {
  112.  
  113.             TRPRINT(TR_LOCK, TR_LEVEL_2, ("new supremum:%s", GETMODE(newMode)));
  114.             lockHeader->supremum = LM_Supremum[newMode][lockHeader->supremum];
  115.         }
  116.  
  117.         /*
  118.          *    put the new mode in the lock entry and put on granted list
  119.          */
  120.         lockEntry->lockMode = newMode;
  121.         listPush( &(lockHeader->grantedList), &(lockEntry->headerList.list) );
  122.         TRPRINT(TR_LOCK, TR_LEVEL_1,
  123.             ("Thread %d, trans %ld, UPGRADing lockEntry 0x%x mode=%s flag=%d",
  124.                 Active->id, Active->message.header.params.in.tid,
  125.                 lockEntry, 
  126.                 GETMODE(lockEntry->lockMode), (int)lockEntry->flags));
  127.         TRPRINT(TR_LOCK, TR_LEVEL_1,
  128.                 ("lock (id %s) entry for trans %d",
  129.                 lockEntry->flags & LOCK_UPGRADE ?
  130.                     printLockId(((LOCKENTRY*)lockEntry->lockHeader)->lockHeader->hashList.lockid) :
  131.                     printLockId(lockEntry->lockHeader->hashList.lockid),
  132.                 lockEntry->headerList.transRec->tid) );
  133.  
  134.  
  135.         /*
  136.          *    return that the lock has been granted
  137.          */
  138.         return(esmNOERROR);
  139.  
  140.     } else {
  141.  
  142.         register LOCKENTRY    *upgradeEntry;
  143.  
  144.  
  145.         TRPRINT(TR_LOCK, TR_LEVEL_2, ("lock upgrade is not grantable"));    
  146.  
  147.         /*
  148.          *    check to see if the caller wishes to wait
  149.          */
  150.         if ((flags & LOCK_NOWAIT) || (flags & LOCK_INSTANT))    {
  151.  
  152.             /*
  153.              *    push the lock entry back onto the granted list
  154.              *    and increment the currently held mode
  155.              */
  156.             listPush( &(lockHeader->grantedList), &(lockEntry->headerList.list) );
  157.             lockHeader->modeCount[lockEntry->lockMode]++;
  158.             SM_ERROR(TYPE_USER, esmLOCKBUSY);
  159.             return(esmFAILURE);
  160.         }
  161.  
  162.         /*
  163.          *    check the deadlock
  164.          */
  165.         if (checkDeadlock(transRec,
  166.                 (LOCKENTRY *) FIRST_LIST_ELEMENT( &(lockHeader->grantedList) )))    {
  167.  
  168.             /*
  169.              *    push the lock entry back onto the granted list
  170.              *    and increment the currently held mode
  171.              */
  172.             listPush( &(lockHeader->grantedList), &(lockEntry->headerList.list) );
  173.             lockHeader->modeCount[lockEntry->lockMode]++;
  174.             return(esmFAILURE);
  175.         }
  176.  
  177.         /*
  178.          *    push the lock entry back onto the granted list
  179.          *    and increment the currently held mode
  180.          */
  181.         listPush( &(lockHeader->grantedList), &(lockEntry->headerList.list) );
  182.         lockHeader->modeCount[lockEntry->lockMode]++;
  183.  
  184.         /*
  185.          *    check to see if the request is in deadlock with any
  186.          *    other upgrades that are pending for this lock
  187.          */
  188.         if (checkUpgradeDeadlock(lockHeader, lockEntry->lockMode, newMode))    {
  189.  
  190.             return(esmFAILURE);
  191.         }
  192.  
  193.         /*
  194.          *    get a new entry and put it on the upgrade list
  195.          */
  196.         if ((upgradeEntry = 
  197.             newLockEntry(transRec, lockHeader, UPGRADE_LIST, newMode))== NULL){
  198.             return(esmFAILURE);
  199.         }
  200.  
  201.         /*
  202.          *    initialize the information in the entry record
  203.          *
  204.          *    CAUTION:
  205.          *  Upgrade entries contain are identical to 
  206.          *  other entries except that the lockHeader
  207.          *  pointer points to the lock entry of the
  208.          *  held lock instead of the actuall lock
  209.          *  header.
  210.          */
  211.         upgradeEntry->lockHeader = (LOCKHEADER *) lockEntry;
  212.  
  213.         /*
  214.          *    mark the upgrade as pending in the master record
  215.          */
  216.         lockEntry->flags |= LOCK_UPGRADE_PENDING;
  217.  
  218.  
  219.         TRPRINT(TR_LOCK, TR_LEVEL_1,
  220.             ("Thread %d, trans %ld, UPGRADing lockEntry 0x%x",
  221.                 Active->id, Active->message.header.params.in.tid,
  222.                 lockEntry));
  223.         TRPRINT(TR_LOCK, TR_LEVEL_1,
  224.             ("upgradeEntry 0x%x, mode=%s flag=%d",
  225.                 upgradeEntry,
  226.                 GETMODE(upgradeEntry->lockMode), (int)upgradeEntry->flags));
  227.         TRPRINT(TR_LOCK, TR_LEVEL_1,
  228.             ("lock (id %s) entry for trans %d",
  229.                 upgradeEntry->flags & LOCK_UPGRADE ?
  230.                     printLockId(((LOCKENTRY*)upgradeEntry->lockHeader)->lockHeader->hashList.lockid) :
  231.                     printLockId(upgradeEntry->lockHeader->hashList.lockid),
  232.                 upgradeEntry->headerList.transRec->tid) );
  233.  
  234.         /*
  235.          *    put the thread on the wait list for this lock
  236.          */
  237.         return awaitLock( transRec->lock_timeout,
  238.             upgradeEntry, THREAD_LOCKUPGRADE_WAIT);
  239.     }
  240. }
  241.